import React, { useState } from 'react';
import styled from 'styled-components';
import { Radio } from 'antd';
import Dot from './components/Dot';
import { Row, Col } from './components/Flexbox';
import { fitLine, findIntersection } from './line';

const Box = styled.div`
  border: 1px solid gray;
  position: relative;
  cursor: crosshair;
`;

const Table = styled.table`
  border: 1px solid gray;
  th {
    text-align: center;
  }
  td {
    border: 1px solid gray;
    padding: 2px 4px;
  }
  td.right {
    text-align: right;
  }
  tfoot {
    td {
      text-align: center;
    }
  }
`;

function CoordinateFrame({
  mode,
  width,
  height,
  points,
  setPoints,
  lines,
  setMouseCoordinate,
}) {
  const [dragging, setDragging] = useState({
    index: -1,
    isDragging: false,
  });
  return (
    <Box
      style={{ width, height }}
      onClick={(e) => {
        if (mode == 'Add') {
          let x = e.clientX - e.target.parentNode.offsetLeft;
          let y = e.clientY - e.target.parentNode.offsetTop;
          let weight = Math.random();
          setPoints([...points, [x, y, weight]]);
        }
      }}
      onMouseUp={() => {
        if (mode == 'Move') {
          setDragging({ isDragging: false });
        }
      }}
      onMouseMove={(e) => {
        let x = e.clientX - e.target.parentNode.offsetLeft;
        let y = e.clientY - e.target.parentNode.offsetTop;
        setMouseCoordinate([x, y]);
        if (mode == 'Move') {
          const { index, isDragging } = dragging;
          if (isDragging) {
            const [x0, y0, weight] = points[index];
            points[index] = [x, y, weight];
            setPoints([...points]);
          }
        }
      }}
    >
      <svg style={{ width, height }}>
        {lines.map(([[x1, y1], [x2, y2]], index) => (
          <line key={index} x1={x1} y1={y1} x2={x2} y2={y2} stroke="blue" />
        ))}
      </svg>
      {points.map((point, index) => (
        <Dot
          key={index}
          index={index}
          mode={mode}
          radius={5}
          point={point}
          setDragging={setDragging}
        />
      ))}
    </Box>
  );
}

function PointList({ points, setPoints }) {
  return (
    <Table>
      <thead>
        <tr>
          <th>X</th>
          <th>Y</th>
          <th>Weight</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        {points.map(([x, y, weight], index) => (
          <tr key={index}>
            <td className="right">{x}</td>
            <td className="right">{y}</td>
            <td>{weight}</td>
            <td>
              <button
                onClick={() => {
                  points.splice(index, 1);
                  setPoints([...points]);
                }}
              >
                X
              </button>
            </td>
          </tr>
        ))}
      </tbody>
      <tfoot>
        <tr>
          <td colSpan={4}>
            <button onClick={() => setPoints([])}>Clear Points</button>
          </td>
        </tr>
      </tfoot>
    </Table>
  );
}

export default function App() {
  const [points, setPoints] = useState([]);
  const [lines, setLines] = useState([]);
  const [width, height] = [600, 400];
  const [method, setMethod] = useState('PCA');
  const [mode, setMode] = useState('Add');
  const [[x, y], setMouseCoordinate] = useState([0, 0]);
  const radioStyle = {
    display: 'block',
  };
  return (
    <Row style={{ padding: 20 }}>
      <Col>
        <Row style={{ padding: '6px 0' }} valign="middle" space="between">
          <Radio.Group
            onChange={(e) => setMode(e.target.value)}
            value={mode}
            optionType="button"
            buttonStyle="solid"
          >
            <Radio.Button value="Add">Add Point</Radio.Button>
            <Radio.Button value="Move">Move Point</Radio.Button>
          </Radio.Group>
          <label style={{ marginBottom: 0 }}>
            ({x},{y})
          </label>
        </Row>
        <CoordinateFrame
          mode={mode}
          width={width}
          height={height}
          points={points}
          setPoints={setPoints}
          lines={lines}
          setMouseCoordinate={setMouseCoordinate}
        />
        <Row style={{ marginTop: 20 }}>
          <Radio.Group
            onChange={(e) => setMethod(e.target.value)}
            value={method}
          >
            <Radio style={radioStyle} value="LS">
              LS
            </Radio>
            <Radio style={radioStyle} value="PCA">
              PCA
            </Radio>
            <Radio style={radioStyle} value="WeightedPCA">
              Weighted PCA
            </Radio>
            <Radio style={radioStyle} value="IterativeReweightedPCA">
              Iterative Reweighted PCA
            </Radio>
          </Radio.Group>
          <button
            onClick={() => {
              if (points.length > 1) {
                let line = fitLine(points, method);
                console.log(line);
                let axis_points = findIntersection(line, [0, 0, width, height]);
                setLines([axis_points]);
              }
            }}
          >
            Fit line
          </button>
        </Row>
      </Col>
      <Col style={{ paddingLeft: 10, paddingTop: 44 }}>
        <PointList points={points} setPoints={setPoints} />
      </Col>
    </Row>
  );
}
